home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectInput / DIConfig / cbitmap.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-11  |  20.3 KB  |  727 lines

  1. //-----------------------------------------------------------------------------
  2. // File: Cbitmap.cpp
  3. //
  4. // Desc: CBitmap class is an object that wraps around a Windows bitmap.
  5. //
  6. // Copyright (C) 1999-2001 Microsoft Corporation. All Rights Reserved.
  7. //-----------------------------------------------------------------------------
  8.  
  9. #include "common.hpp"
  10. #include "id3dsurf.h"
  11.  
  12.  
  13. BOOL DI_AlphaBlend(
  14.   HDC hdcDest,                 // handle to destination DC
  15.   int nXOriginDest,            // x-coord of upper-left corner
  16.   int nYOriginDest,            // y-coord of upper-left corner
  17.   int nWidthDest,              // destination width
  18.   int nHeightDest,             // destination height
  19.   HDC hdcSrc,                  // handle to source DC
  20.   int nXOriginSrc,             // x-coord of upper-left corner
  21.   int nYOriginSrc,             // y-coord of upper-left corner
  22.   int nWidthSrc,               // source width
  23.   int nHeightSrc              // source height
  24. )
  25. {
  26.     LPBYTE pbDestBits = NULL;
  27.     HBITMAP hTempDestDib = NULL;
  28.     int nXOriginDestLogical = nXOriginDest, nYOriginDestLogical = nYOriginDest;
  29.  
  30.     // Convert nXOriginDest and nYOriginDest from logical coord to device coord
  31.     POINT pt = {nXOriginDest, nYOriginDest};
  32.     LPtoDP(hdcDest, &pt, 1);
  33.     nXOriginDest = pt.x;
  34.     nYOriginDest = pt.y;
  35.     // Convert nXOriginSrc and nYOriginSrc from logical coord to device coord
  36.     pt.x = nXOriginSrc;
  37.     pt.y = nYOriginSrc;
  38.     LPtoDP(hdcSrc, &pt, 1);
  39.     nXOriginSrc = pt.x;
  40.     nYOriginSrc = pt.y;
  41.  
  42.     // Get the bits for both source and destination first
  43.     // Every BITMAP used in the UI is created with CreateDIBSection, so we know we can get the bits.
  44.     HBITMAP hSrcBmp, hDestBmp;
  45.     DIBSECTION SrcDibSec, DestDibSec;
  46.     hSrcBmp = (HBITMAP)GetCurrentObject(hdcSrc, OBJ_BITMAP);
  47.     GetObject(hSrcBmp, sizeof(DIBSECTION), &SrcDibSec);
  48.     hDestBmp = (HBITMAP)GetCurrentObject(hdcDest, OBJ_BITMAP);
  49.     GetObject(hDestBmp, sizeof(DIBSECTION), &DestDibSec);
  50.     if (!SrcDibSec.dsBm.bmBits) return FALSE;  // Not necessary, but to be absolutely safe.
  51.  
  52.     // Calculate the rectangle to perform the operation.
  53.     if (nXOriginSrc + nWidthSrc > SrcDibSec.dsBm.bmWidth) nWidthSrc = SrcDibSec.dsBm.bmWidth - nXOriginSrc;
  54.     if (nYOriginSrc + nHeightSrc > SrcDibSec.dsBm.bmHeight) nHeightSrc = SrcDibSec.dsBm.bmHeight - nYOriginSrc;
  55.     if (nXOriginDest + nWidthDest > DestDibSec.dsBm.bmWidth) nWidthDest = DestDibSec.dsBm.bmWidth - nXOriginDest;
  56.     if (nYOriginDest + nHeightDest > DestDibSec.dsBm.bmHeight) nHeightDest = DestDibSec.dsBm.bmHeight - nYOriginDest;
  57.  
  58.     if (nWidthDest > nWidthSrc) nWidthDest = nWidthSrc;
  59.     if (nHeightDest > nHeightSrc) nHeightDest = nHeightSrc;
  60.     if (nWidthSrc > nWidthDest) nWidthSrc = nWidthDest;
  61.     if (nHeightSrc > nHeightDest) nHeightSrc = nHeightDest;
  62.  
  63.     BITMAPINFO bmi;
  64.     ZeroMemory(&bmi.bmiHeader, sizeof(BITMAPINFOHEADER));
  65.     bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  66.     bmi.bmiHeader.biWidth = nWidthDest;
  67.     bmi.bmiHeader.biHeight = nHeightDest;
  68.     bmi.bmiHeader.biPlanes = 1;
  69.     bmi.bmiHeader.biBitCount = 32;
  70.     bmi.bmiHeader.biCompression = BI_RGB;
  71.  
  72.     // Bitmap will have the same width as the dest, but only lines covered in the subrect.
  73.     hTempDestDib = CreateDIBSection(hdcDest, &bmi, DIB_RGB_COLORS, (LPVOID*)&pbDestBits, NULL, NULL);
  74.     if (!hTempDestDib)
  75.         return FALSE;
  76.  
  77.     HDC hTempDC = CreateCompatibleDC(hdcDest);
  78.     if (!hTempDC)
  79.     {
  80.         DeleteObject(hTempDestDib);
  81.         return FALSE;
  82.     }
  83.     HBITMAP hOldTempBmp = (HBITMAP)SelectObject(hTempDC, hTempDestDib);
  84.     BOOL res = BitBlt(hTempDC, 0, 0, nWidthDest, nHeightDest, hdcDest, nXOriginDestLogical, nYOriginDestLogical, SRCCOPY);
  85.     SelectObject(hTempDC, hOldTempBmp);
  86.     DeleteDC(hTempDC);
  87.     if (!res)
  88.     {
  89.         DeleteObject(hTempDestDib);
  90.         return FALSE;
  91.     }
  92.  
  93.     // We have the bits. Now do the blend.
  94.     for (int j = 0; j < nHeightSrc; ++j)
  95.     {
  96.         assert(j >= 0 &&
  97.                j < nHeightDest);
  98.         LPBYTE pbDestRGB = (LPBYTE)&((DWORD*)pbDestBits)[j * nWidthDest];
  99.  
  100.         assert(nYOriginSrc+SrcDibSec.dsBm.bmHeight-nHeightSrc >= 0 &&
  101.                nYOriginSrc+SrcDibSec.dsBm.bmHeight-nHeightSrc < SrcDibSec.dsBm.bmHeight);
  102.         LPBYTE pbSrcRGBA = (LPBYTE)&((DWORD*)SrcDibSec.dsBm.bmBits)[(j+nYOriginSrc+SrcDibSec.dsBm.bmHeight-nHeightSrc)
  103.                                                                     * SrcDibSec.dsBm.bmWidth + nXOriginSrc];
  104.  
  105.         for (int i = 0; i < nWidthSrc; ++i)
  106.         {
  107.             // Blend
  108.             if (pbSrcRGBA[3] == 255)
  109.             {
  110.                 // Alpha is 255. straight copy.
  111.                 *(LPDWORD)pbDestRGB = *(LPDWORD)pbSrcRGBA;
  112.             } else
  113.             if (pbSrcRGBA[3])
  114.             {
  115.                 // Alpha is non-zero
  116.                 pbDestRGB[0] = pbSrcRGBA[0] + (((255-pbSrcRGBA[3]) * pbDestRGB[0]) >> 8);
  117.                 pbDestRGB[1] = pbSrcRGBA[1] + (((255-pbSrcRGBA[3]) * pbDestRGB[1]) >> 8);
  118.                 pbDestRGB[2] = pbSrcRGBA[2] + (((255-pbSrcRGBA[3]) * pbDestRGB[2]) >> 8);
  119.             }
  120.             pbDestRGB += sizeof(DWORD);
  121.             pbSrcRGBA += sizeof(DWORD);
  122.         }  // for
  123.     } // for
  124.  
  125.     HDC hdcTempDest = CreateCompatibleDC(hdcDest);
  126.     if (hdcTempDest)
  127.     {
  128.         HBITMAP hOldTempBmp = (HBITMAP)SelectObject(hdcTempDest, hTempDestDib);  // Select the temp dib for blitting
  129.         // Get logical coord for device coord of dest origin
  130.         POINT pt = {nXOriginDest, nYOriginDest};
  131.         DPtoLP(hdcDest, &pt, 1);
  132.         BitBlt(hdcDest, pt.x, pt.y, nWidthDest, nHeightDest,
  133.                hdcTempDest, 0, 0, SRCCOPY);
  134.         SelectObject(hdcTempDest, hOldTempBmp);
  135.         DeleteDC(hdcTempDest);
  136.     }
  137.  
  138.     DeleteObject(hTempDestDib);
  139.     return TRUE;
  140. }
  141.  
  142. CBitmap::~CBitmap()
  143. {
  144.     if (m_hbm != NULL)
  145.         DeleteObject(m_hbm);
  146.     m_hbm = NULL;
  147.     m_bSizeKnown = FALSE;
  148. }
  149.  
  150. HDC CreateAppropDC(HDC hDC)
  151. {
  152.     return CreateCompatibleDC(hDC);
  153. }
  154.  
  155. HBITMAP CreateAppropBitmap(HDC hDC, int cx, int cy)
  156. {
  157.     if (hDC != NULL)
  158.         return CreateCompatibleBitmap(hDC, cx, cy);
  159.     
  160.     HWND hWnd = GetDesktopWindow();
  161.     HDC hWDC = GetWindowDC(hWnd);
  162.     HBITMAP hbm = NULL;
  163.     if (hWDC != NULL)
  164.     {
  165.         hbm = CreateCompatibleBitmap(hWDC, cx, cy);
  166.         ReleaseDC(hWnd, hWDC);
  167.     }
  168.  
  169.     return hbm;
  170. }
  171.  
  172. CBitmap *CBitmap::CreateFromResource(HINSTANCE hInst, LPCTSTR tszName)
  173. {
  174.     return CreateViaLoadImage(hInst, tszName, IMAGE_BITMAP, 0, 0,
  175.         LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
  176. }
  177.  
  178. CBitmap *CBitmap::CreateFromFile(LPCTSTR tszFileName)
  179. {
  180.     return CreateViaD3DX(tszFileName);
  181. }
  182.  
  183. // Use D3DX API to load our surface with image content.
  184. CBitmap *CBitmap::CreateViaD3DX(LPCTSTR tszFileName, LPDIRECT3DSURFACE8 pUISurf)
  185. {
  186.     HRESULT hr;
  187.     LPDIRECT3DDEVICE8 pD3DDev = NULL;
  188.     LPDIRECT3DTEXTURE8 pTex = NULL;
  189.     LPDIRECT3DSURFACE8 pSurf = NULL;
  190.     HBITMAP hDIB = NULL;
  191.     CBitmap *pbm = NULL;
  192.  
  193.     // If the UI surface is NULL, create a new device.  Otherwise, use existing device.
  194.     if (!pUISurf)
  195.     {
  196.         LPDIRECT3D8 pD3D = Direct3DCreate8(D3D_SDK_VERSION);
  197.  
  198.         if (!pD3D)
  199.         {
  200.             OutputDebugString(_T("Failed to create D3D\n"));
  201.             hr = E_FAIL;
  202.         }
  203.         else
  204.         {
  205.             D3DDISPLAYMODE Mode;
  206.             pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &Mode);
  207.             D3DPRESENT_PARAMETERS d3dpp;
  208.             d3dpp.BackBufferWidth = 1;
  209.             d3dpp.BackBufferHeight = 1;
  210.             d3dpp.BackBufferFormat = Mode.Format;
  211.             d3dpp.BackBufferCount = 1;
  212.             d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
  213.             d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
  214.             d3dpp.hDeviceWindow = NULL;
  215.             d3dpp.Windowed = TRUE;
  216.             d3dpp.EnableAutoDepthStencil = FALSE;
  217.             d3dpp.FullScreen_RefreshRateInHz = 0;
  218.             d3dpp.FullScreen_PresentationInterval = 0;
  219.             d3dpp.Flags = 0;
  220.             hr = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, GetActiveWindow(), D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pD3DDev);
  221.             if (FAILED(hr))
  222.             {
  223.                 TCHAR tszMsg[MAX_PATH];
  224.  
  225.                 _stprintf(tszMsg, _T("CreateDevice returned 0x%X\n"), hr);
  226.                 OutputDebugString(tszMsg);
  227.             }
  228.             
  229.             pD3D->Release();
  230.         }
  231.     } 
  232.     else
  233.     {
  234.         hr = pUISurf->GetDevice(&pD3DDev);
  235.     }
  236.  
  237.  
  238.     if( FAILED( hr ) )
  239.     {
  240.         OutputDebugString(_T("Failed to create D3D device\n"));
  241.     }
  242.     else if( FAILED( hr = pD3DDev->CreateTexture(512, 512, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pTex) ) ) 
  243.     {
  244.         OutputDebugString(_T("Failed to create D3D texture\n"));
  245.     }
  246.     else if( FAILED( hr = pTex->GetSurfaceLevel(0, &pSurf) ) )
  247.     {
  248.         OutputDebugString(_T("Failed to obtain surface interface\n"));
  249.     }
  250.     else
  251.     {
  252.         D3DXIMAGE_INFO d3dii;
  253.  
  254.         if( SUCCEEDED( D3DXLoadSurfaceFromFile(pSurf, NULL, NULL, tszFileName, NULL, D3DX_FILTER_NONE, 0, &d3dii) ) )
  255.         {
  256.             // Create a bitmap and copy the texture content onto it.
  257.             int iDibWidth = d3dii.Width, iDibHeight = d3dii.Height;
  258.             if (iDibWidth > 430) iDibWidth = 430;
  259.             if (iDibHeight > 310) iDibHeight = 310;
  260.             LPBYTE pDIBBits;
  261.             BITMAPINFO bmi;
  262.             bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
  263.             bmi.bmiHeader.biWidth = iDibWidth;
  264.             bmi.bmiHeader.biHeight = iDibHeight;
  265.             bmi.bmiHeader.biPlanes = 1;
  266.             bmi.bmiHeader.biBitCount = 32;
  267.             bmi.bmiHeader.biCompression = BI_RGB;
  268.             bmi.bmiHeader.biSizeImage = 0;
  269.             bmi.bmiHeader.biXPelsPerMeter = 0;
  270.             bmi.bmiHeader.biYPelsPerMeter = 0;
  271.             bmi.bmiHeader.biClrUsed = 0;
  272.             bmi.bmiHeader.biClrImportant = 0;
  273.             hDIB = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (LPVOID*)&pDIBBits, NULL, 0);
  274.             if (hDIB)
  275.             {
  276.                 // Pre-process the pixel data based on alpha for AlphaBlend()
  277.                 D3DLOCKED_RECT lrc;
  278.                 pSurf->LockRect(&lrc, NULL, NULL);
  279.                 BYTE *pbData = (LPBYTE)lrc.pBits;
  280.                 {
  281.                     for (DWORD i = 0; i < 512 * 512; ++i)
  282.                     {
  283.                         BYTE bAlpha = pbData[i * 4 + 3];
  284.                         pbData[i * 4] = pbData[i * 4] * bAlpha / 255;
  285.                         pbData[i * 4 + 1] = pbData[i * 4 + 1] * bAlpha / 255;
  286.                         pbData[i * 4 + 2] = pbData[i * 4 + 2] * bAlpha / 255;
  287.                     }
  288.                 }
  289.                 pSurf->UnlockRect();
  290.  
  291.                 // Lock the surface
  292.                 D3DLOCKED_RECT D3DRect;
  293.                 hr = pSurf->LockRect(&D3DRect, NULL, 0);
  294.                 if (SUCCEEDED(hr))
  295.                 {
  296.                     // Copy the bits
  297.                     // Note that the image is reversed in Y direction, so we need to re-reverse it.
  298.                     for (int y = 0; y < iDibHeight; ++y)
  299.                         CopyMemory(pDIBBits + ((iDibHeight-1-y) * iDibWidth * 4), (LPBYTE)D3DRect.pBits + (y * D3DRect.Pitch), iDibWidth * 4);
  300.  
  301.                     // Unlock
  302.                     pSurf->UnlockRect();
  303.  
  304.                     pbm = new CBitmap;
  305.  
  306.                     if (pbm) 
  307.                     {
  308.                         pbm->m_hbm = hDIB;
  309.                         hDIB = NULL;
  310.                         pbm->FigureSize();
  311.                     }
  312.                 }
  313.             }
  314.         }
  315.     }
  316.  
  317.     if (hDIB) DeleteObject(hDIB);
  318.     if (pSurf) pSurf->Release();
  319.     if (pTex) pTex->Release();
  320.     if (pD3DDev) pD3DDev->Release();
  321.  
  322.     return pbm;
  323. }
  324.  
  325. CBitmap *CBitmap::CreateViaLoadImage(HINSTANCE hInst, LPCTSTR tszName, UINT uType, int cx, int cy, UINT fuLoad)
  326. {
  327.     if (fuLoad & LR_SHARED)
  328.     {
  329.         assert(0);
  330.         return NULL;
  331.     }
  332.  
  333.     CBitmap *pbm = new CBitmap;
  334.     if (pbm == NULL)
  335.         return NULL;
  336.     
  337.     HANDLE handle = ::LoadImage(hInst, tszName, uType, cx, cy, fuLoad);
  338.     
  339.     if (handle == NULL)
  340.     {
  341.         delete pbm;
  342.         return NULL;
  343.     }
  344.  
  345.     pbm->m_hbm = (HBITMAP)handle;
  346.  
  347.     pbm->FigureSize();
  348.  
  349.     return pbm;
  350. }
  351.  
  352. BOOL CBitmap::FigureSize()
  353. {
  354.     BITMAP bm;
  355.  
  356.     if (0 == GetObject((HGDIOBJ)m_hbm, sizeof(BITMAP), (LPVOID)&bm))
  357.         return FALSE;
  358.  
  359.     m_size.cx = abs(bm.bmWidth);
  360.     m_size.cy = abs(bm.bmHeight);
  361.  
  362.     return m_bSizeKnown = TRUE;
  363. }
  364.  
  365. CBitmap *CBitmap::StealToCreate(HBITMAP &refbm)
  366. {
  367.     if (refbm == NULL)
  368.         return NULL;
  369.  
  370.     CBitmap *pbm = new CBitmap;
  371.     if (pbm == NULL)
  372.         return NULL;
  373.     
  374.     pbm->m_hbm = refbm;
  375.     refbm = NULL;
  376.  
  377.     pbm->FigureSize();
  378.  
  379.     return pbm;
  380. }
  381.  
  382. BOOL CBitmap::GetSize(SIZE *psize)
  383. {
  384.     if (m_hbm == NULL || !m_bSizeKnown || psize == NULL)
  385.         return FALSE;
  386.  
  387.     *psize = m_size;
  388.     return TRUE;
  389. }
  390.  
  391. void CBitmap::AssumeSize(SIZE size)
  392. {
  393.     m_size = size;
  394.     m_bSizeKnown = TRUE;  //m_hbm != NULL;
  395. }
  396.  
  397. CBitmap *CBitmap::CreateResizedTo(SIZE size, HDC hDC, int iStretchMode, BOOL bStretch)
  398. {
  399.     CBitmap *pbm = new CBitmap;
  400.     HDC hSrcDC = NULL;
  401.     HDC hDestDC = NULL;
  402.     HBITMAP hBitmap = NULL;
  403.     HGDIOBJ hOldSrcBitmap = NULL, hOldDestBitmap = NULL;
  404.     BOOL bRet = FALSE;
  405.     int oldsm = 0;
  406.     POINT brushorg;
  407.  
  408.     if (pbm == NULL || size.cx < 1 || size.cy < 1 || m_hbm == NULL || !m_bSizeKnown)
  409.         goto error;
  410.  
  411.     hSrcDC = CreateAppropDC(hDC);
  412.     hDestDC = CreateAppropDC(hDC);
  413.     if (hSrcDC == NULL || hDestDC == NULL)
  414.         goto error;
  415.  
  416.     hBitmap = CreateAppropBitmap(hDC, size.cx, size.cy);
  417.     if (hBitmap == NULL)
  418.         goto error;
  419.  
  420.     if (bStretch)
  421.     {
  422.         if (GetStretchBltMode(hDestDC) != iStretchMode)
  423.         {
  424.             if (iStretchMode == HALFTONE)
  425.                 GetBrushOrgEx(hDestDC, &brushorg);
  426.             oldsm = SetStretchBltMode(hDestDC, iStretchMode);
  427.             if (iStretchMode == HALFTONE)
  428.                 SetBrushOrgEx(hDestDC, brushorg.x, brushorg.y, NULL);
  429.         }
  430.     }
  431.  
  432.     hOldSrcBitmap = SelectObject(hSrcDC, m_hbm);
  433.     hOldDestBitmap = SelectObject(hDestDC, hBitmap);
  434.     if (bStretch)
  435.         bRet = StretchBlt(hDestDC, 0, 0, size.cx, size.cy, hSrcDC, 0, 0, m_size.cx, m_size.cy, SRCCOPY);
  436.     else
  437.         bRet = BitBlt(hDestDC, 0, 0, size.cx, size.cy, hSrcDC, 0, 0, SRCCOPY);
  438.     SelectObject(hDestDC, hOldDestBitmap);
  439.     SelectObject(hSrcDC, hOldSrcBitmap);
  440.  
  441.     if (bStretch)
  442.     {
  443.         if (oldsm != 0)
  444.         {
  445.             if (oldsm == HALFTONE)
  446.                 GetBrushOrgEx(hDestDC, &brushorg);
  447.             SetStretchBltMode(hDestDC, oldsm);
  448.             if (oldsm == HALFTONE)
  449.                 SetBrushOrgEx(hDestDC, brushorg.x, brushorg.y, NULL);
  450.         }
  451.     }
  452.  
  453.     if (!bRet)
  454.         goto error;
  455.  
  456.     pbm->m_hbm = hBitmap;
  457.     hBitmap = NULL;
  458.     pbm->AssumeSize(size);
  459.  
  460.     goto cleanup;
  461. error:
  462.     if (pbm != NULL)
  463.         delete pbm;
  464.     pbm = NULL;
  465. cleanup:
  466.     if (hBitmap != NULL)
  467.         DeleteObject(hBitmap);
  468.     if (hSrcDC != NULL)
  469.         DeleteDC(hSrcDC);
  470.     if (hDestDC != NULL)
  471.         DeleteDC(hDestDC);
  472.  
  473.     return pbm;
  474. }
  475.  
  476. HDC CBitmap::BeginPaintInto(HDC hCDC)
  477. {
  478.     if (m_hDCInto != NULL)
  479.     {
  480.         assert(0);
  481.         return NULL;
  482.     }
  483.  
  484.     m_hDCInto = CreateAppropDC(hCDC);
  485.     if (m_hDCInto == NULL)
  486.         return NULL;
  487.  
  488.     m_hOldBitmap = SelectObject(m_hDCInto, m_hbm);
  489.  
  490.     return m_hDCInto;
  491. }
  492.  
  493. void CBitmap::EndPaintInto(HDC &hDC)
  494. {
  495.     if (hDC == NULL || hDC != m_hDCInto)
  496.     {
  497.         assert(0);
  498.         return;
  499.     }
  500.  
  501.     SelectObject(m_hDCInto, m_hOldBitmap);
  502.     DeleteDC(m_hDCInto);
  503.     m_hDCInto = NULL;
  504.     hDC = NULL;
  505. }
  506.  
  507. void CBitmap::PopOut()
  508. {
  509.     if (m_hDCInto == NULL)
  510.     {
  511.         assert(0);
  512.         return;
  513.     }
  514.  
  515.     SelectObject(m_hDCInto, m_hOldBitmap);
  516. }
  517.  
  518. void CBitmap::PopIn()
  519. {
  520.     if (m_hDCInto == NULL)
  521.     {
  522.         assert(0);
  523.         return;
  524.     }
  525.  
  526.     m_hOldBitmap = SelectObject(m_hDCInto, m_hbm);
  527. }
  528.  
  529. BOOL CBitmap::Draw(HDC hDC, POINT origin, SIZE crop, BOOL bAll)
  530. {
  531.     if (hDC == NULL || m_hbm == NULL)
  532.         return FALSE;
  533.  
  534.     if (bAll && !m_bSizeKnown)
  535.         return FALSE;
  536.  
  537.     if (bAll)
  538.         crop = m_size;
  539.  
  540.     HDC hDCbm = CreateAppropDC(hDC);
  541.     if (hDCbm == NULL)
  542.         return FALSE;
  543.  
  544.     BOOL bPop = m_hDCInto != NULL;
  545.  
  546.     if (bPop)
  547.         PopOut();
  548.  
  549.     HGDIOBJ hOldBitmap = SelectObject(hDCbm, m_hbm);
  550.     BOOL bRet = BitBlt(hDC, origin.x, origin.y, crop.cx, crop.cy, hDCbm, 0, 0, SRCCOPY);
  551.     SelectObject(hDCbm, hOldBitmap);
  552.     DeleteDC(hDCbm);
  553.  
  554.     if (bPop)
  555.         PopIn();
  556.  
  557.     return bRet;
  558. }
  559.  
  560. BOOL CBitmap::Blend(HDC hDC, POINT origin, SIZE crop, BOOL bAll)
  561. {
  562.     if (hDC == NULL || m_hbm == NULL)
  563.         return FALSE;
  564.  
  565.     if (bAll && !m_bSizeKnown)
  566.         return FALSE;
  567.  
  568.     if (bAll)
  569.         crop = m_size;
  570.  
  571.     HDC hDCbm = CreateAppropDC(hDC);
  572.     if (hDCbm == NULL)
  573.         return FALSE;
  574.  
  575.     BOOL bPop = m_hDCInto != NULL;
  576.  
  577.     if (bPop)
  578.         PopOut();
  579.  
  580. #ifndef AC_SRC_ALPHA
  581. #define AC_SRC_ALPHA AC_SRC_NO_PREMULT_ALPHA
  582. #endif
  583.  
  584.     HGDIOBJ hOldBitmap = SelectObject(hDCbm, m_hbm);
  585.     BOOL bRet;
  586.  
  587.     bRet = DI_AlphaBlend(hDC, origin.x, origin.y, crop.cx, crop.cy, hDCbm, 0, 0, m_size.cx, m_size.cy);
  588.     SelectObject(hDCbm, hOldBitmap);
  589.     DeleteDC(hDCbm);
  590.  
  591.     if (bPop)
  592.         PopIn();
  593.  
  594.     return bRet;
  595. }
  596.  
  597. CBitmap *CBitmap::Dup()
  598. {   
  599.     SIZE t;
  600.     if (!GetSize(&t))
  601.         return NULL;
  602.     return CreateResizedTo(t, NULL, COLORONCOLOR, FALSE);
  603. }
  604.  
  605. CBitmap *CBitmap::Create(SIZE size, HDC hCDC)
  606. {
  607.     CBitmap *pbm = new CBitmap;
  608.     if (pbm == NULL)
  609.         return NULL;
  610.  
  611.     pbm->m_hbm = CreateAppropBitmap(hCDC, size.cx, size.cy);
  612.     if (pbm->m_hbm == NULL)
  613.     {
  614.         delete pbm;
  615.         return NULL;
  616.     }
  617.  
  618.     pbm->AssumeSize(size);
  619.  
  620.     return pbm;
  621. }
  622.  
  623. CBitmap *CBitmap::Create(SIZE size, COLORREF color, HDC hCDC)
  624. {
  625.     CBitmap *pbm = Create(size, hCDC);
  626.     if (pbm == NULL)
  627.         return NULL;
  628.  
  629.     HDC hDC = pbm->BeginPaintInto();
  630.     if (hDC == NULL)
  631.     {
  632.         delete pbm;
  633.         return NULL;
  634.     }
  635.     
  636.     HGDIOBJ hBrush = (HGDIOBJ)CreateSolidBrush(color), hOldBrush;
  637.  
  638.     if (hBrush)
  639.     {
  640.         hOldBrush = SelectObject(hDC, hBrush);
  641.         Rectangle(hDC, -1, -1, size.cx + 1, size.cy + 1);
  642.         SelectObject(hDC, hOldBrush);
  643.         DeleteObject(hBrush);
  644.     }
  645.  
  646.     pbm->EndPaintInto(hDC);
  647.  
  648.     return pbm;
  649. }
  650.  
  651. BOOL CBitmap::Get(HDC hDC, POINT point)
  652. {
  653.     if (!m_bSizeKnown)
  654.         return FALSE;
  655.     return Get(hDC, point, m_size);
  656. }
  657.  
  658. BOOL CBitmap::Get(HDC hDC, POINT point, SIZE size)
  659. {
  660.     if (m_hDCInto != NULL || hDC == NULL)
  661.         return FALSE;
  662.  
  663.     HDC hDCInto = BeginPaintInto(hDC);
  664.     if (hDCInto == NULL)
  665.         return FALSE;
  666.  
  667.     BOOL bRet = BitBlt(hDCInto, 0, 0, size.cx, size.cy, hDC, point.x, point.y, SRCCOPY);
  668.     
  669.     EndPaintInto(hDCInto);
  670.  
  671.     return bRet;
  672. }
  673.  
  674. CBitmap *CBitmap::CreateHorzGradient(const RECT &rect, COLORREF rgbLeft, COLORREF rgbRight)
  675. {
  676.     SIZE size = GetRectSize(rect);
  677.     COLORREF rgbMid = RGB(
  678.         (int(GetRValue(rgbLeft)) + int(GetRValue(rgbRight))) / 2,
  679.         (int(GetGValue(rgbLeft)) + int(GetGValue(rgbRight))) / 2,
  680.         (int(GetBValue(rgbLeft)) + int(GetBValue(rgbRight))) / 2);
  681.     return Create(size, rgbMid);
  682. }
  683.  
  684. BOOL CBitmap::MapToDC(HDC hDCTo, HDC hDCMapFrom)
  685. {
  686.     if (hDCTo == NULL || !m_bSizeKnown || m_hDCInto != NULL)
  687.         return FALSE;
  688.  
  689.     HBITMAP hbm = CreateAppropBitmap(hDCTo, m_size.cx, m_size.cy);
  690.     if (hbm == NULL)
  691.         return FALSE;
  692.  
  693.     HDC hDCFrom = NULL;
  694.     HDC hDCInto = NULL;
  695.     HGDIOBJ hOld = NULL;
  696.     BOOL bRet = FALSE;
  697.  
  698.     hDCFrom = BeginPaintInto(hDCMapFrom);
  699.     if (!hDCFrom)
  700.         goto cleanup;
  701.  
  702.     hDCInto = CreateCompatibleDC(hDCTo);
  703.     if (!hDCInto)
  704.         goto cleanup;
  705.  
  706.     hOld = SelectObject(hDCInto, (HGDIOBJ)hbm);
  707.     bRet = BitBlt(hDCInto, 0, 0, m_size.cx, m_size.cy, hDCFrom, 0, 0, SRCCOPY);
  708.     SelectObject(hDCInto, hOld);
  709.  
  710. cleanup:
  711.     if (hDCFrom)
  712.         EndPaintInto(hDCFrom);
  713.     if (hDCInto)
  714.         DeleteDC(hDCInto);
  715.     if (bRet)
  716.     {
  717.         if (m_hbm)
  718.             DeleteObject((HGDIOBJ)m_hbm);
  719.         m_hbm = hbm;
  720.         hbm = NULL;
  721.     }
  722.     if (hbm)
  723.         DeleteObject((HGDIOBJ)hbm);
  724.  
  725.     return bRet;
  726. }
  727.